#include "UserInputDataProcessor.h"

UserInputDataProcessor::UserInputDataProcessor()
    :flightNum(0),queryPointNum(0),currentLine(1)
{
    FlightData.resize(1); QueryPointData.resize(1); //QueryPointData_Point.resize(1);
    FlightData[0].push_back(L"飞行线编号"); FlightData[0].push_back(L"飞行线端点1坐标"); FlightData[0].push_back(L"飞行线端点2坐标"); //FlightData[0].push_back(L"查询点到飞行线距离");
    QueryPointData[0].push_back(L"查询点坐标"); QueryPointData[0].push_back(L"距离最近的飞行线编号"); QueryPointData[0].push_back(L"距离大小");
    //QueryPointData_Point[0].push_back(L"查询点坐标");
}

int UserInputDataProcessor::getFlightNum() {
    return flightNum;
}

int UserInputDataProcessor::getQueryPointNum() {
    return queryPointNum;
}

int UserInputDataProcessor::getCurrentLine() {
    return currentLine;
}

void UserInputDataProcessor::getFlightDataReference(vector<vector<wstring>>& newdata) {
    newdata = FlightData;
}

void UserInputDataProcessor::getQueryPointDataReference(vector<vector<wstring>>& newdata) {
    newdata = QueryPointData;
}

void UserInputDataProcessor::getQueryPointData_PointReference(vector<vector<wstring>>& newdata) {
    newdata.resize(queryPointNum + 1);
    newdata[0].push_back(L"查询点坐标");
    for (int i = 1; i <= queryPointNum; ++i) {
        newdata[i].push_back(QueryPointData[i][0]);
    }
    return;

    //newdata = QueryPointData_Point;
}






pair<double, double> UserInputDataProcessor::findClosestPointOnSegment(double Px, double Py,
    double Ax, double Ay,
    double Bx, double By) const {
    // 向量AB
    double ABx = Bx - Ax;
    double ABy = By - Ay;

    // 向量AP
    double APx = Px - Ax;
    double APy = Py - Ay;

    // 计算AB长度的平方
    double AB2 = ABx * ABx + ABy * ABy;

    // 计算AP与AB的点积
    double AP_AB = APx * ABx + APy * ABy;

    // 计算参数t，表示最近点在线段AB上的位置比例
    double t = AP_AB / AB2;

    // 检查最近点是否在线段上
    if (t <= 0.0) {
        // 最近点是A点
        return make_pair(Ax, Ay);
    }
    else if (t >= 1.0) {
        // 最近点是B点
        return make_pair(Bx, By);
    }
    else {
        // 垂足在线段上
        return make_pair(Ax + t * ABx, Ay + t * ABy);
    }
}

// 共用的数据结构初始化
void UserInputDataProcessor::initDataStructures(
    int flight_num,
    int query_point_num,
    bool resizeFlightLines
    ){
    int final_flight_num = (flight_num == -1) ? flightNum : flight_num;
    int final_query_num = (query_point_num == -1) ? queryPointNum : query_point_num;


    FlightData.resize(final_flight_num + 1);
    for (int i = 1; i < FlightData.size(); ++i) {
        FlightData[i].clear();
    }
    QueryPointData.resize(final_query_num + 1);
    for (int i = 1; i < QueryPointData.size(); ++i) {
        QueryPointData[i].clear();
    }

    if (resizeFlightLines) {
        FlightLines.clear();
        FlightLines.resize(final_flight_num);
        QueryPoints.clear();
        QueryPoints.resize(final_query_num);
    }
}

void UserInputDataProcessor::processFlightLine(int id, double x1, double y1, double x2, double y2) {
    FlightLines[id - 1] = { id, x1, y1, x2, y2 };
    
    wstring xy1 = L"(" + formatCoord(x1)+ L"," + formatCoord(y1) + L")";
    wstring xy2 = L"(" + formatCoord(x2)+ L"," + formatCoord(y2) + L")";

    FlightData[id].push_back(to_wstring(id));
    FlightData[id].push_back(xy1);
    FlightData[id].push_back(xy2);
}

void UserInputDataProcessor::processQueryPoint(int id, double x, double y) {
    QueryPoints[id - 1] = { x, y };

    wstring xy = L"(" + formatCoord(x) + L"," + formatCoord(y)+ L")";
    QueryPointData[id].push_back(xy);
}

int UserInputDataProcessor::readDataFile(wstring filePath) {
    currentLine = 1;
    //判断传入的文件路径是不是.txt或.csv
    if (!isSupportedFile(filePath)) return -1;//如果不是则提示用户传入.txt或.csv文件
    wifstream file(filePath);
    if (!file.is_open()) {
        return 0; // 文件打开失败
    }
    try {
        // 根据扩展名处理
        size_t dotPos = filePath.find_last_of(L".");
        wstring ext = filePath.substr(dotPos + 1);
        transform(ext.begin(), ext.end(), ext.begin(), ::towlower);

        if (ext == L"txt") {
            return readTextFile(file);
        }
        else if (ext == L"csv") {
            return readCSVFile(file);
        }
    }
    catch (...) {
        return -404; // 未知错误
    }
    return -2;  //文件打得开，但不是txt和csv文件 
    // return 0;  文件打开失败
    // return -1; 不是.txt或.csv
    // return -2; 文件打得开，但不是txt和csv文件 
    // return -3; 数据存在错误信息
    // return -4; 

}

// CSV行分割辅助函数
vector<wstring> UserInputDataProcessor::splitCSVLine(const wstring& line) {
   vector<wstring> result;
   wstringstream ss(line);
   wstring field;

     while (getline(ss, field, L',')) {
        // 去除首尾空格
        size_t start = field.find_first_not_of(L" ");
        size_t end = field.find_last_not_of(L" ");
        if (start != wstring::npos && end != wstring::npos) {
            result.push_back(field.substr(start, end - start + 1));
        } else {
            result.push_back(L""); // 空字段
        }
    }
    return result;
}

int UserInputDataProcessor::readCSVFile(wifstream& file) {
    wstring line;
    // 读取首行：飞行线数量,查询点数量
    if (!getline(file, line)) return -3;
    vector<wstring> header = splitCSVLine(line);
    if (header.size() != 2) return -3;
    try {
        // 先验证格式再转换
        if (!isValidNumber(header[0])) return -3;
        if (!isValidNumber(header[1])) return -3;
        flightNum = stoi(header[0]);
        queryPointNum = stoi(header[1]);

    }
    catch (...) {
        return -3; // 数值转换失败
    }
    // 验证数量有效性
    if (flightNum < 0 || queryPointNum < 0) return -3;
    //// 初始化数据结构
    initDataStructures();

    // 读取飞行线数据
    for (int i = 1; i <= flightNum; ++i) {
        if (!getline(file, line)) return -3;
        vector<wstring> parts = splitCSVLine(line);
        if (parts.size() != 4) return -3;
        if (!isValidNumber2(parts[0])) return -3;
        if (!isValidNumber2(parts[1])) return -3;
        if (!isValidNumber2(parts[2])) return -3;
        if (!isValidNumber2(parts[3])) return -3;
        try {
            double x1 = stod(parts[0]);
            double y1 = stod(parts[1]);
            double x2 = stod(parts[2]);
            double y2 = stod(parts[3]);
            processFlightLine(i, x1, y1, x2, y2);
        }
        catch (...) {
            return -3; // 坐标转换失败
        }
    }

    // 读取查询点数据
    for (int i = 1; i <= queryPointNum; ++i) {
        if (!getline(file, line)) return -3;
        vector<wstring> parts = splitCSVLine(line);
        if (parts.size() != 2) return -3;
        if (!isValidNumber2(parts[0])) return -3;
        if (!isValidNumber2(parts[1])) return -3;
        try {
            double x = stod(parts[0]);
            double y = stod(parts[1]);
            processQueryPoint(i, x, y);
        }
        catch (...) {
            return -3; // 坐标转换失败
        }
    }

    findNearestFlightLineKDTree(FlightLines, QueryPoints);
    return 1;
}

int UserInputDataProcessor::readTextFile(wifstream& file) {
    wstring line;

    if (!getline(file, line)) return -3;
    wistringstream header(line);
    if (!(header >> flightNum >> queryPointNum)) return -3;
    // 验证数量有效性
    if (flightNum < 0 || queryPointNum < 0) return -3;
    initDataStructures();

        for (int i = 1; i <= flightNum; ++i) {
            if (!getline(file, line)) return -3;
            wistringstream ss(line);
            double four = 4, x1, y1, x2, y2;
            if (!(ss >> x1 >> y1 >> x2 >> y2)) return -3;
            // 检查多余数据
            wstring temp;
            if (ss >> temp) return -3;
            processFlightLine(i, x1, y1, x2, y2);
        }
        for (int i = 1; i <= queryPointNum; ++i) {
            //QueryPointData[i].push_back(to_wstring(i)); //编号输入
            if (!getline(file, line)) return -3;
            wistringstream ss(line);
            int two = 2;double x, y;
            if (!(ss >> x >> y)) return -3;
            // 检查多余数据
            wstring temp;
            if (ss >> temp) return -3;
            processQueryPoint(i, x, y);
        }
    /* results = findNearestFlightLine(FlightLines,QueryPoints);
     for (int i = 1; i <= results.size(); ++i) {
         QueryPointData[1].push_back(to_wstring(results[i]));
         QueryPointData[1].push_back();
     }
     */
    findNearestFlightLineKDTree(FlightLines, QueryPoints);
    return 1; //返回1表示成功
}

void UserInputDataProcessor::finishDirectInput(){
    int linenumber = DirectlyInputFlightLines.size();
    int quertnumber = DirectlyInputQueryPoints.size();

    flightNum = linenumber;
    queryPointNum = quertnumber;
    initDataStructures();

    for (int i = 1; i <=linenumber; ++i) {

        FlightLines[i - 1] = {
            i, 
            DirectlyInputFlightLines[i-1].x1,
            DirectlyInputFlightLines[i-1].y1,
            DirectlyInputFlightLines[i-1].x2,
            DirectlyInputFlightLines[i-1].y2
        };
        //FlightLines[i-1].id = i;

        wstring xy1 = L"(" + formatCoord(DirectlyInputFlightLines[i-1].x1) + L"," + formatCoord(DirectlyInputFlightLines[i-1].y1) + L")";
        wstring xy2 = L"(" + formatCoord(DirectlyInputFlightLines[i-1].x2) + L"," + formatCoord(DirectlyInputFlightLines[i-1].y2) + L")";
        FlightData[i].push_back(to_wstring(i));
        FlightData[i].push_back(xy1);
        FlightData[i].push_back(xy2);
    }
    for (int i = 1; i <= quertnumber; ++i) {
        QueryPoints[i - 1] = { DirectlyInputQueryPoints[i-1].x, DirectlyInputQueryPoints[i-1].y};

        wstring xy = L"(" + formatCoord(DirectlyInputQueryPoints[i-1].x) + L"," + formatCoord(DirectlyInputQueryPoints[i-1].y) + L")";
        QueryPointData[i].push_back(xy);
    }
    findNearestFlightLineKDTree(FlightLines, QueryPoints);
}

// 构建KD树
shared_ptr<KDNode> UserInputDataProcessor::buildKDTree(vector<FlightLine>& flightLines, int depth) {
    if (flightLines.empty()) return nullptr;

    int axis = depth % 2; // 交替选择分割轴
    int mid = flightLines.size() / 2;

    // 按包围盒中位数分割
    nth_element(flightLines.begin(), flightLines.begin() + mid, flightLines.end(),
        [axis](const FlightLine& a, const FlightLine& b) {
            auto a_bb = a.getBoundingBox();
            auto b_bb = b.getBoundingBox();
            double a_mid = axis == 0 ? (a_bb.first.first + a_bb.second.first) / 2
                : (a_bb.first.second + a_bb.second.second) / 2;
            double b_mid = axis == 0 ? (b_bb.first.first + b_bb.second.first) / 2
                : (b_bb.first.second + b_bb.second.second) / 2;
            return a_mid < b_mid;
        });

    auto bb = flightLines[mid].getBoundingBox();
    double splitVal = axis == 0 ? (bb.first.first + bb.second.first) / 2
        : (bb.first.second + bb.second.second) / 2;

    auto node = make_shared<KDNode>(flightLines[mid], axis, splitVal);

    // 划分左右子树
    vector<FlightLine> leftLines, rightLines;
    for (size_t i = 0; i < flightLines.size(); ++i) {
        if (i == mid) continue;

        auto cur_bb = flightLines[i].getBoundingBox();
        double minVal = axis == 0 ? cur_bb.first.first : cur_bb.first.second;
        double maxVal = axis == 0 ? cur_bb.second.first : cur_bb.second.second;

        if (maxVal <= splitVal) {
            leftLines.push_back(flightLines[i]);
        }
        else if (minVal >= splitVal) {
            rightLines.push_back(flightLines[i]);
        }
        else {
            // 跨越分割平面的线段同时加入左右子树
            leftLines.push_back(flightLines[i]);
            rightLines.push_back(flightLines[i]);
        }
    }

    node->left = buildKDTree(leftLines, depth + 1);
    node->right = buildKDTree(rightLines, depth + 1);

    return node;
}

// 计算两点距离的平方（避免开方提高效率）
double UserInputDataProcessor::distanceSquared(double x1, double y1, double x2, double y2) {
    double dx = x1 - x2;
    double dy = y1 - y2;
    return dx * dx + dy * dy;
}


// 计算点到线段的最短距离（与之前相同）
double UserInputDataProcessor::pointToLineDistance(double px, double py, const FlightLine& line) {
    double x1 = line.x1, y1 = line.y1;
    double x2 = line.x2, y2 = line.y2;

    double dx = x2 - x1;
    double dy = y2 - y1;
    double lineLengthSq = dx * dx + dy * dy;

    // 如果线段长度为0，退化为点到点距离
    if (lineLengthSq == 0) {
        return sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
    }

    // 计算投影参数t
    double t = ((px - x1) * dx + (py - y1) * dy) / lineLengthSq;
    t = max(0.0, min(1.0, t)); // 限制t在[0,1]范围内

    // 计算投影点坐标
    double projectionX = x1 + t * dx;
    double projectionY = y1 + t * dy;

    // 返回点到投影点的距离
    return sqrt((px - projectionX) * (px - projectionX) + (py - projectionY) * (py - projectionY));
}


void UserInputDataProcessor::searchKDTree(shared_ptr<KDNode> node, const QueryPoint& query,
    double& minDist, int& nearestId) {
    if (!node) return;

    // 计算当前线段的真实距离
    double currentDist = pointToLineDistance(query.x, query.y, node->line);
    if (currentDist < minDist) {
        minDist = currentDist;
        nearestId = node->id;
    }

    // 决定搜索顺序
    double queryVal = node->axis == 0 ? query.x : query.y;
    bool goLeftFirst = queryVal < node->splitValue;

    // 优先搜索更近的分支
    if (goLeftFirst) {
        searchKDTree(node->left, query, minDist, nearestId);
        // 检查是否需要搜索另一分支
        if (queryVal - minDist <= node->splitValue) {
            searchKDTree(node->right, query, minDist, nearestId);
        }
    }
    else {
        searchKDTree(node->right, query, minDist, nearestId);
        // 检查是否需要搜索另一分支
        if (queryVal + minDist >= node->splitValue) {
            searchKDTree(node->left, query, minDist, nearestId);
        }
    }
}

// 使用KD树优化查找最近飞行线
void UserInputDataProcessor::findNearestFlightLineKDTree(const vector<FlightLine>& flightLines, const vector<QueryPoint>& queryPoints) {
    vector<FlightLine> linesCopy = flightLines;
    auto root = buildKDTree(linesCopy);
    //vector<int> results;
    int num = 1; //后加入的代码
    for (const auto& qp : queryPoints) {
        #undef max 
        double minDist = numeric_limits<double>::max();
        int nearestId = -1;
        searchKDTree(root, qp, minDist, nearestId);

        //results.push_back(nearestId);
        QueryPointData[num].push_back(to_wstring(nearestId));  //后加入的代码
        QueryPointData[num].push_back(to_wstring(minDist));//后加入的代码
        ++num; //后加入的代码
    }

    //return results;

}


//vector<FlightLine> linesCopy = flightLines;
    //auto root = buildKDTree(linesCopy);
    //int num = 1; //后加入的代码
    //vector<int> results;
    //for (const auto& qp : queryPoints) {
    //    #undef max 
    //    double minDist = numeric_limits<double>::max();
    //    int nearestId = -1;
    //    // 先用KD树找到最近的中点（近似解）
    //    nearestNeighborSearch(root, qp, 0, minDist, nearestId);
    //    // 由于KD树存储的是中点，我们需要在所有飞行线中精确计算距离
    //    // 但可以只检查KD树返回的候选飞行线，减少计算量
    //    #undef max 
    //    double exactMinDist = numeric_limits<double>::max();
    //    int exactNearestId = -1;
    //    for (const auto& line : flightLines) {
    //        double dist = pointToLineDistance(qp.x, qp.y, line.x1, line.y1, line.x2, line.y2);
    //        if (dist < exactMinDist) {
    //            exactMinDist = dist;
    //            exactNearestId = line.id;
    //        }
    //    }
    //    QueryPointData[num].push_back(to_wstring(exactNearestId));  //后加入的代码
    //    QueryPointData[num].push_back(to_wstring(exactMinDist));//后加入的代码
    //    results.push_back(exactNearestId);
    //    ++num; //后加入的代码
    //}
    //return results;
//// KD树最近邻搜索
//void UserInputDataProcessor::nearestNeighborSearch(shared_ptr<KDNode> node, const QueryPoint& query, int depth, double& minDist, int& nearestId) {
//    if (!node) return;
//
//    double currentDist = distanceSquared(query.x, query.y, node->point[0], node->point[1]);
//    if (currentDist < minDist) {
//        minDist = currentDist;
//        nearestId = node->id;
//    }
//
//    int axis = depth % 2;
//    bool goLeft = (axis == 0) ? (query.x < node->point[0]) : (query.y < node->point[1]);
//
//    // 优先搜索更可能包含最近邻的分支
//    if (goLeft) {
//        nearestNeighborSearch(node->left, query, depth + 1, minDist, nearestId);
//    }
//    else {
//        nearestNeighborSearch(node->right, query, depth + 1, minDist, nearestId);
//    }
//
//    // 检查另一分支是否可能有更近的点
//    double remainingDist = (axis == 0) ?
//        (query.x - node->point[0]) * (query.x - node->point[0]) :
//        (query.y - node->point[1]) * (query.y - node->point[1]);
//    if (remainingDist < minDist) {
//        if (goLeft) {
//            nearestNeighborSearch(node->right, query, depth + 1, minDist, nearestId);
//        }
//        else {
//            nearestNeighborSearch(node->left, query, depth + 1, minDist, nearestId);
//        }
//    }
//}
//暴力方法求解最近飞行线
//void UserInputDataProcessor::findNearestFlightLine(const vector<FlightLine>& flightLines, const vector<QueryPoint>& queryPoints) {
//    vector<int> results;
//    int num = 1; //后加入的代码
//    for (const auto& qp : queryPoints) {
//        double minDistance = 1.7976931348623157e+308;
//        int nearestLineId = -1;
//        for (const auto& line : flightLines) {
//            double distance = pointToLineDistance(qp.x, qp.y, line.x1, line.y1, line.x2, line.y2);
//            if (distance < minDistance) {
//                minDistance = distance;
//                nearestLineId = line.id;
//            }
//        }
//        QueryPointData[num].push_back(to_wstring(nearestLineId));  //后加入的代码
//        QueryPointData[num].push_back(to_wstring(minDistance));//后加入的代码
//        results.push_back(nearestLineId);
//        ++num; //后加入的代码
//    }
//    return;
//    //return results;
//}

